package com.novanok.campaigntweets;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.auth.AccessToken;

public class Campania extends Thread implements Serializable{

    private String nombre; //nombre de la Campaña.
    private String descripcion; // descripcion de la Campaña.
    private ArrayList<Tweet> tweets; // Tweets Programados que se van a usar en la Campaña.
    private ArrayList<Palabra> palabras; // Palabras que se van a trackear para la Campaña.
    private ArrayList<String> usuariosAExcluir; // Usuarios que se van a excluir de la Campaña.
    private Date ultimoEnvio; // Fecha del ultimo envio de tweets.
    private ArrayList<String> usuariosTrackeados; // Lista de Usuarios trackeados a los cuales se les van a enviar los tweets.
    private int tiempoEnvio; // En Segundos
    private int cantidadEnvios; // Cantidad de envios que se van a hacer.
    private int cantidadUsuarios;
    private boolean procesa; // Variable que determina si se procesa.

    private int cantidadUsuariosTrackeados;
    private int cantidadTweetsEnviados;
    private Calendar tiempoProximoEnvio;

    private String estado;

    public Campania(){
        this.setCantidadEnvios( 1 );
        this.setTiempoEnvio( 30 );
        this.setCantidadUsuarios( 10 );
        this.setNombre( "" );
        this.setDescripcion( "" );
        this.setTweets( new ArrayList<Tweet>() );
        this.setPalabras( new ArrayList<Palabra>() );
        this.setUsuariosAExcluir( new ArrayList<String>() );
        this.setUsuariosTrackeados( new ArrayList<String>() );

        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(System.currentTimeMillis());
        this.setTiempoProximoEnvio(c);

        this.setEstado("Creada");
    }

    public Campania( String nombre, String descripcion ){
        this.setCantidadEnvios( 1 );
        this.setTiempoEnvio( 30 );
        this.setCantidadUsuarios( 10 );
        this.setNombre( nombre );
        this.setDescripcion( descripcion );
        this.setTweets( new ArrayList<Tweet>() );
        this.setPalabras( new ArrayList<Palabra>() );
        this.setUsuariosAExcluir( new ArrayList<String>() );
        this.setUsuariosTrackeados( new ArrayList<String>() );

        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(System.currentTimeMillis());
        this.setTiempoProximoEnvio(c);

        this.setEstado("Creada");
    }

    public void run(){
        while ( this.isProcesa() ){
            try {
                this.setEstado("Proceso en Espera...");

                Calendar c = Calendar.getInstance();
                c.setTimeInMillis(System.currentTimeMillis() + ( this.tiempoEnvio * 60000 ));
                this.setTiempoProximoEnvio( c );

                Thread.sleep( this.tiempoEnvio * 60000 );
                synchronized ( this.getUsuariosTrackeados() ) {
                    if ( this.getUsuariosTrackeados().size() > 0 ) {
                        this.enviarTweets();
                        this.getUsuariosTrackeados().clear();
                        this.setCantidadUsuariosTrackeados(0);
                    }
                }
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }
        }
    }

    public void iniciar(){
        this.setEstado("Campaña Iniciada");
        this.setCantidadTweetsEnviados(0);
        this.setProcesa(true);
        this.start();
    }

    public void detener(){
        this.setEstado("Deteniendo Campaña...");
        this.setProcesa(false);

        while ( this.isAlive() );

        this.setEstado("Campaña Detenida");
    }

    public String getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String apellido) {
        this.descripcion = apellido;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public ArrayList<Tweet> getTweets() {
        return tweets;
    }

    public void setTweets(ArrayList<Tweet> tweets) {
        this.tweets = tweets;
    }

    public ArrayList<Palabra> getPalabras() {
        return palabras;
    }

    public void setPalabras(ArrayList<Palabra> palabras) {
        this.palabras = palabras;
    }

    public void enviarTweets( ){
        this.setEstado("Enviando Tweets...");

        Twitter tw = TwitterUtil.getInstance().getTwitter();
        tw.setOAuthAccessToken(new AccessToken( MyActivity.getAccessToken(), MyActivity.getAccessTokenSecret() ));

        for ( int i = 0; i < this.getCantidadEnvios(); i++ ){
            for ( Tweet tweet : this.getTweets() ) {
                try {
                    String texto = tweet.getDescripcion().trim();
                    StringBuilder textoFinal = new StringBuilder(texto);

                    ArrayList<String> tweeetsFinales = new ArrayList<String>();

                    for ( int k = 0; k < this.getUsuariosTrackeados().size() && k < this.getCantidadUsuarios() ; k++ ){
                        if ( ( textoFinal.toString().trim().length() + this.getUsuariosTrackeados().get( k ).length() + 2 ) >= 140 ) {
                            tweeetsFinales.add( textoFinal.toString().trim() );
                            textoFinal = new StringBuilder(texto);
                        }

                        textoFinal.append(" @" + this.getUsuariosTrackeados().get( k ).trim());
                    }

                    if ( tweeetsFinales.size() == 0 )
                        tweeetsFinales.add( textoFinal.toString().trim() );

                    for ( String t : tweeetsFinales ) {
                        tw.updateStatus( t );
                        this.setCantidadTweetsEnviados( this.getCantidadTweetsEnviados() + 1 );
                        Thread.sleep( 5000 );
                    }

                    this.setEstado("Tweets Enviados");
                } catch ( TwitterException e ) {
                    e.printStackTrace();

                } catch ( InterruptedException e ) {
                    e.printStackTrace();
                }
            }
        }
    }

    public ArrayList<String> getUsuariosAExcluir() {
        return usuariosAExcluir;
    }

    public void setUsuariosAExcluir( ArrayList<String> usuariosAExcluir ) {
        this.usuariosAExcluir = usuariosAExcluir;
    }

    public Date getUltimoEnvio() {
        return ultimoEnvio;
    }

    public void setUltimoEnvio(Date ultimoEnvio) {
        this.ultimoEnvio = ultimoEnvio;
    }

    public ArrayList<String> getUsuariosTrackeados() {
        return usuariosTrackeados;
    }

    public void setUsuariosTrackeados( ArrayList<String> usuariosTrackeados ) {
        this.usuariosTrackeados = usuariosTrackeados;
    }

    public void verificarTweetConPalabras( Status tweet ){
        synchronized ( this.getPalabras() ) {
            for ( Palabra p2 : this.getPalabras() )
                if ( tweet.getText().toUpperCase().contains( p2.getDescripcion().toUpperCase() )
                        && !existeUsuarioNoPermitido( tweet.getUser().getScreenName() )
                        && this.getUsuariosTrackeados().size() < this.getCantidadUsuarios() ) {
                    this.getUsuariosTrackeados().add( tweet.getUser().getScreenName() );
                    cantidadUsuariosTrackeados++;
                    break;
                }
        }
    }

    private boolean existeUsuarioNoPermitido ( String usuario ){
        for ( String usu : this.getUsuariosAExcluir() )
            if ( usu.compareTo( usuario ) == 0 )
                return true;

        return false;
    }

    public int getTiempoEnvio() {
        return tiempoEnvio;
    }

    public void setTiempoEnvio( int tiempoEnvio ) {
        this.tiempoEnvio = tiempoEnvio;
    }

    public int getCantidadEnvios() {
        return cantidadEnvios;
    }

    public void setCantidadEnvios( int cantidadEnvios ) {
        this.cantidadEnvios = cantidadEnvios;
    }

    public boolean isProcesa() {
        return procesa;
    }

    public void setProcesa( boolean procesa ) {
        this.procesa = procesa;
    }

    public int getCantidadUsuarios() {
        return cantidadUsuarios;
    }

    public void setCantidadUsuarios( int cantidadUsuarios ) {
        this.cantidadUsuarios = cantidadUsuarios;
    }

    public int getCantidadUsuariosTrackeados() {
        return cantidadUsuariosTrackeados;
    }

    public void setCantidadUsuariosTrackeados(int cantidadUsuariosTrackeados) {
        this.cantidadUsuariosTrackeados = cantidadUsuariosTrackeados;
    }

    public Calendar getTiempoProximoEnvio() {
        return tiempoProximoEnvio;
    }

    public void setTiempoProximoEnvio(Calendar tiempoProximoEnvio) {
        this.tiempoProximoEnvio = tiempoProximoEnvio;
    }

    public int getCantidadTweetsEnviados() {
        return cantidadTweetsEnviados;
    }

    public void setCantidadTweetsEnviados(int cantidadTweetsEnviados) {
        this.cantidadTweetsEnviados = cantidadTweetsEnviados;
    }

    public String getEstado() {
        return estado;
    }

    public void setEstado(String estado) {
        this.estado = estado;
    }
}